package cn.player.download;

import android.content.Context;
import android.text.TextUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;

import cn.player.download.db.DbManager;
import cn.player.download.file.Files;
import cntv.player.core.util.LogUtil;

public class DownloadFileTask implements Runnable, Comparable<DownloadFileTask> {
    private DownloadInfo mEntity;
    private DownloadTaskCallback downloadTaskCallback;
    private DbManager mDbManager;
    private boolean mIsContinue = true;
    private boolean mDeleteTag;
    private int priority;


    public DownloadFileTask(Context context, DownloadInfo entity, DownloadTaskCallback downloadTaskCallback) {
        mDbManager = DbManager.getInstance(context);
        mEntity = entity;
        this.downloadTaskCallback = downloadTaskCallback;
    }

    public DownloadFileTask(Context context, DownloadInfo entity, int priority, DownloadTaskCallback downloadTaskCallback) {
        mDbManager = DbManager.getInstance(context);
        mEntity = entity;
        this.priority = priority;
        this.downloadTaskCallback = downloadTaskCallback;
    }

    @Override
    public int compareTo(DownloadFileTask downloadFileTask) {
        if (priority < downloadFileTask.priority) {
            return -1;
        } else if (priority > downloadFileTask.priority) {
            return 1;
        } else {
            return 0;
        }
    }

    public void setOnDownloadTaskCallback(DownloadTaskCallback downloadTaskCallback) {
        this.downloadTaskCallback = downloadTaskCallback;
    }

    public DownloadTaskCallback getOnDownloadTaskCallback() {
        return downloadTaskCallback;
    }

    public DownloadInfo getEntity() {
        return mEntity;
    }

    public void updateDownloadInfoState(int downloadState) {
        mEntity.setDownloadState(downloadState);
        mDbManager.update(mEntity.getVid(), downloadState);
    }

    @Override
    public void run() {

        createFileDir();

        DownloadInfo findInfo = mDbManager.find(mEntity.getVid());
        if (findInfo == null) {//说明是第一次下载
            mEntity.setDownloadState(DownloadInfo.DOWNLOAD_ING);
            mDbManager.insert(mEntity);
            startDownload();
            return;
        }

        if (findInfo.getDownloadState() == DownloadInfo.DOWNLOAD_SUCCESS
                && checkFileExist()) {//以前下载过,并且下载成功
//            LogUtil.u("文件已下载,filename = " + mEntity.getFilename());
            mEntity.setDownloadState(DownloadInfo.DOWNLOAD_SUCCESS);
            if (downloadTaskCallback != null) {
                downloadTaskCallback.onDownloadCompleted(mEntity);
            }
            return;
        }

        if (findInfo.getDownloadState() == DownloadInfo.DOWNLOAD_ING) {
            LogUtil.u("文件正在下载...,filename = " + mEntity.getFilename());
            return;
        }

        mDbManager.update(mEntity.getVid(), DownloadInfo.DOWNLOAD_ING, mEntity.getTargetFilePath());
        startDownload();

    }

    public void startDownload() {
        String m3u8FilePath = downloadM3u8File(mEntity.getRequestUrl());
        if (TextUtils.isEmpty(m3u8FilePath)) {
            updateDownloadInfoState(DownloadInfo.DOWNLOAD_ERR);
            return;
        }

        boolean downloadState = downloadTsFiles(m3u8FilePath);
        if (downloadState) {
            updateDownloadInfoState(DownloadInfo.DOWNLOAD_SUCCESS);
            if (downloadTaskCallback != null) {
                downloadTaskCallback.onDownloadCompleted(mEntity);
            }
        } else {
            updateDownloadInfoState(DownloadInfo.DOWNLOAD_ERR);
            Files.delete(mEntity.getTargetFilePath());
        }
    }

    private boolean checkFileExist() {
        File file = new File(mEntity.getTargetFilePath(), mEntity.getFilename());
        return file.exists();
    }

    private void createFileDir() {
        File file = new File(mEntity.getTargetFilePath());
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    private String downloadM3u8File(String targetUrl) {
        if (downloadTaskCallback != null) {
            downloadTaskCallback.onDownloadStarted(mEntity);
        }

        File file = new File(mEntity.getTargetFilePath(), mEntity.getFilename());
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            file.createNewFile();

            URL url = new URL(targetUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            inputStream = conn.getInputStream();

            outputStream = new FileOutputStream(file);
            int len;
            byte[] buf = new byte[1024];
            while ((len = inputStream.read(buf)) != -1) {
                outputStream.write(buf, 0, len);
            }
            return file.getPath();
        } catch (Exception e) {
            e.printStackTrace();
            if (downloadTaskCallback != null) {
                downloadTaskCallback.onDownloadFailed(mEntity, e);
            }
            if (e != null) {
                LogUtil.e("zl", "downloadM3u8File() err = " + e.getMessage());
            }
            return null;
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private boolean downloadTsFiles(String m3u8FilePath) {
        List<String> tsFileList = M3u8FileHelper.getM3u8VideoUrlList(mEntity.getRequestUrl(), m3u8FilePath);
        for (String tsFilePath : tsFileList) {
            boolean tsFileState = downloadTsFile(tsFilePath);
            if (!tsFileState) {
                return false;
            }
        }
        return true;
    }

    private boolean downloadTsFile(String tsFilePath) {
        String tsFileName = tsFilePath.substring(tsFilePath.lastIndexOf("/") + 1);
        File file = new File(mEntity.getTargetFilePath(), tsFileName);
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            file.createNewFile();

            URL url = new URL(tsFilePath);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            inputStream = conn.getInputStream();

            outputStream = new FileOutputStream(file);
            int fileLength = conn.getContentLength();
            int len = 0;
            byte[] buffer = new byte[1024];

            int downloadFileLength = 0;
            float mLastProgress = 0;
            while (downloadFileLength < fileLength) {
                len = inputStream.read(buffer);
                outputStream.write(buffer, 0, len);
                downloadFileLength += len;

                /*float percent = downloadFileLength / (float) fileLength * 100;
                if (100f == percent) {
                    updateDownloadInfoState(DownloadInfo.DOWNLOAD_SUCCESS);
                }
                float progress = (float) (Math.round(percent * 10)) / 10;// 保留一位小数
                mEntity.setProgress(progress);
                // 更新完成或者下载进度比上次大于0.15才更新前台，否则大文件更新太频繁了
                if (null != downloadTaskCallback && (100f == mEntity.getProgress() || mEntity.getProgress() - mLastProgress >= 0.15f)) {
                    mLastProgress = mEntity.getProgress();
                    downloadTaskCallback.onDownloadUpdate(mEntity);
                }*/
            }

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            if (downloadTaskCallback != null) {
                downloadTaskCallback.onDownloadFailed(mEntity, e);
            }
            if (e != null) {
                LogUtil.e("zl", "err = " + e.getMessage());
            }
            return false;
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public interface DownloadTaskCallback {
        void onDownloadStarted(DownloadInfo entity);

        void onDownloadUpdate(DownloadInfo entity);

        void onDownloadCompleted(DownloadInfo entity);

        void onDownloadPaused(DownloadInfo entity);

        void onDownloadCanceled(DownloadInfo entity);

        void onDownloadFailed(DownloadInfo entity, Throwable e);

        /**
         * 线程池中的任务全部执行完毕
         */
        void onNoTaskAlive();


    }
}
